"ui nodejs";
import $JavaArray from "autojs-create-javaarray";
import $ui from "ui";
import { showToast as toast } from 'toast';
import { delay } from 'lang';
await import("./importClass.js");

const $java = $autojs.java;

var CurrentName;

importClass(android.app.AlertDialog);
importClass(com.google.android.material.dialog.MaterialAlertDialogBuilder);
importClass(com.google.android.material.snackbar.Snackbar);
importClass("dalvik.system.PathClassLoader");
importClass(java.lang.Thread);
importClass("dalvik.system.DexFile");
importClass(android.os.Build);
importClass(java.util.Collections);
importClass(java.util.LinkedHashSet);

var dalvik = Packages["dalvik"];
var ctx = $autojs.androidContext;

class MyActivity extends $ui.Activity {
    get ui() {
        return new Proxy(this, {
            get: (target, key) => {
                return this.contentView.findView(key);
            },
        })
    };

    get initialStatusBar() {
        return {
            color: "#ffffff",
            light: false
        };
    }

    get layoutXml() {
        return `
<column>
    <appbar w="*" h="auto">
        <toolbar id="toolbar" title="Java查询"/>
    </appbar>
    <column>
        <android.widget.Button id="类信息" text="搜索类信息" textSize="18" style="Widget.AppCompat.Button.Borderless.Colored" textColor="#737373"/>
    </column>
</column>
        `
    }
    
    index = 0;

    special = [
        ["java.util.Properties", {
            "load": ["java.io.InputStream/java.io.Reader input", "从文件中加载properties文件"],
            "loadFromXML": ["java.io.InputStream input", "从xml文件中加载文件"],
            "setProperty": ["String key,Object value", "设置key的值为value"],
            "getProperty": ["String key", "获取key的值"],
            "store": ["java.io.OutputStream output,String description", "储存文件"]
        }, "\"properties\"是一个文件格式,而java.util.Properties则是一个处理properties文件的类。"],
        ["java.lang.Thread", {
            "java.lang.Thread": ["java.lang.Runnable runnable", "创建一个新的线程"],
            "start": ["", "开始线程"],
            "interrupt": ["", "打扰线程(注意!此函数已停用!)"],
            "setPriority": ["int priority", "设置线程优先级"],
            "setUncaughtExceptionHandler": ["java.lang.Thread$UncaughtExceptionHandler uncaughtExceptionHandler", "设置线程错误处理器"]
        }, "\"java.lang.Thread\"是一个实用的类,它可以开启新线程，提高运行效率。"]
    ]
    
    annotations = {
        "java.lang.Deprecated": "已停用",
        "java.lang.Override": "重写属性",
        "java.lang.SuppressWarnings": "忽略警告",
        "sun.reflect.CallerSensitive": "堵住漏洞"
    }
    
    blocks = {
        "Public": "公开",
        "Private": "私有",
        "Protected": "受保护",
        "Static": "静态",
        "Native": "内部",
        "Final": "常量",
        "Abstract": "抽象",
        "Synchronized": "锁",
        "Transient": "跳过序列化",
        "Volatile": "同步"
    }
    
    primitives={
        "int": "整数",
        "float": "浮点数",
        "long": "长整数",
        "char": "字符",
        "double": "双浮点数",
        "byte": "字节",
        "boolean": "布尔值",
        "short": "短整数",
        "void": "无"
    }
    
    scbuf = [];
    res;
    
    alert(tile, message){
        new MaterialAlertDialogBuilder(this)
            .setTitle(""+tile)
            .setMessage("" + message)
            .create()
            .show();
    }
    
    translateAnnotation(annotation){
        return this.annotations[annotation] ? this.annotations[annotation] : annotation;
    }
    
    translatePrimitive(primitive){
        return this.primitives[primitive] ? this.primitives[primitive] : primitive;
    }

    translateBlock(block) {
        return this.blocks[block] ? this.blocks[block] : block;
    }
    
    getSuperClass(s,str,n){
        try{
            var sp = s.getSuperclass();
            var se = n == 0 ? "\n" : "┕";
            for(let i=0; i<n; i++){
                se+="--"
            }
            str.push(se+">"+sp.getName());
            n++;
            this.scbuf=[sp,str,n];
            this.getSuperClass(sp,str,n);
        }catch(e){
            this.res=[sp,str,n];
        }
    }

    getModifier(bi) {
        bi = bi.getModifiers();
        var sbuf = [];
        var a = java.lang.reflect.Modifier.class.getMethods();
        for (var buf = 0; buf < a.length; buf++) {
            if (a[buf].getName().startsWith("is")) {
                if (java.lang.reflect.Modifier[a[buf].getName()](bi) == true) {
                    var has = false
                    for (var i in sbuf) {
                        if (sbuf[i] == String(a[buf].getName()).replace(/^is/, "")) {
                            has = true
                            break
                        }
                    }
                    if (!has) {
                        sbuf.push(this.translateBlock(String(a[buf].getName()).replace(/^is/, "")));
                    }
                }
            }
        }
        return sbuf;
    }

    getStaticSpecific(field) {
        return ("名字:" + field.getName() + "\n属性:" + this.getModifier(field).join(",") + "\n类型:" + this.translatePrimitive(field.getType().getName()));
    }

    getStatic(name) {
        var a = Packages[name].class.getDeclaredFields()
        var b = {};
        for (let i = 0; i < a.length; i++) {
            b[a[i].getName()] = this.getStaticSpecific(a[i])
        }
        var bi = []
        for (var j in b) {
            bi.push(b[j])
        }
        this.alert("字段", bi.join("\n\n\n"));
    }
    
    getMethod(method){
        var re=[];
        for(let n = 0; n < method.getParameterTypes().length; n++){
            re.push(this.translatePrimitive(method.getParameterTypes()[n].getName()))
        }
        var r=[]
        for(let k = 0; k < method.getExceptionTypes().length; k++){
            r.push(method.getExceptionTypes()[k].getName())
        }
        var rr=[]
        for(let l = 0; l < method.getDeclaredAnnotations().length; l++){
            rr.push(method.getDeclaredAnnotations()[l].annotationType().getName())
        }
        return ("方法:"+method.getName()+"\n属性:"+this.getModifier(method).join(",")+"\n参数:"+re.join(",")+"\n返回值:"+this.translatePrimitive(method.getReturnType().getName())+"\n可能发生的错误:"+r.join()+"\n注释:"+this.translateAnnotation(rr.join()))
    }
    
    getMethods(name){
        var a=Packages[name].class.getMethods()
        var b=[]
        for(var i = 0; i < a.length; i++){
          b.push(this.getMethod(a[i]))
        }
        this.alert("方法",b.join("\n\n\n"))
    }
    
    getMainInfo(name){
        var a = Packages[name].class;
        var b = [];
        try {
            try {
                if(!a.isInterface()){
                    this.getSuperClass(a,[],1)
                    b.push("继承关系:\n>"+a.getName()+"\n"+this.res[1].join("\n"))
                    this.res=null
                }
            } catch (e) {
                b.push(e);
            }
            b.push("是原生类:"+a.isPrimitive());
            b.push("是代理者:"+a.isProxy());
            b.push("是接口:"+a.isInterface());
            b.push("是枚举:"+a.isEnum());
            b.push("包名:"+a.getPackage().getName());
            b.push("标记:"+a.getSigners());
            var gi=a.getDeclaredClasses();
            var arria=[];
            for(let suxj = 0; suxj < gi.length; suxj++){
                arria.push(gi[suxj].getName());
            }
            b.push("内部类和接口:\n"+arria.join("\n"));
            var ge=a.getDeclaredAnnotations();
            var arris=[];
            for(let sxj = 0; sxj < ge.length; sxj++){
                arris.push(ge[sxj].getName());
            }
            b.push("内部注释:\n"+arris.join("\n"));
            var _interface=[]
            for(var interc = 0; interc < a.getInterfaces().length; interc++){
                _interface.push(a.getInterfaces()[interc].getName());
            }
            b.push("复写接口:"+_interface.join(","));
            
        } catch (e) {
            b.push("发现错误!\n错误信息:")
            for(var i in e){
                b.push(i+":"+e[i]);
            }
        }
        
        this.alert("详细信息",b.join("\n\n\n"));
    }
    
    getConstructor(c){
        var re=[]
        for(var n = 0; n < c.getParameterTypes().length; n++){
            re.push(this.translatePrimitive(c.getParameterTypes()[n].getName()))
        }
        var r=[]
        for(var k = 0; k < c.getExceptionTypes().length; k++){
            r.push(c.getExceptionTypes()[k].getName())
        }
        var rr=[]
        for(var l = 0; l < c.getDeclaredAnnotations().length; l++){
            rr.push(c.getDeclaredAnnotations()[l].annotationType().getName())
        }
        return "方法:"+c.getName()+"\n属性:"+this.getModifier(c).join(",")+"\n参数:"+re.join(",")+"\n可能发生的错误:"+r.join()+"\n注释:"+this.translateAnnotation(rr.join())
    }

    getConstructors(name){
        var a = Packages[name].class.getConstructors()
        var b = []
        for(var i = 0; i < a.length; i++){
          b.push(this.getConstructor(a[i]))
        }
        this.alert("构造函数",b.join("\n\n\n"))
    }
    
    showMethod(name,target){
        var a=Packages[name].class.getMethods();
        var b=[];
        var re=[];
        var r=[];
        var rr=[];
        
        for(let i = 0; i < a.length; i++){
            if(a[i]!=null){
                if(a[i].getName()==String(target)){
                    b.push(this.getMethod(a[i]));
                }
            }
        }
        
        a=Packages[name].class.getDeclaredFields()
        var c={}
        for(let i = 0; i < a.length; i++){
            if(a[i].getName()==String(target)){
                c[a[i].getName()]=this.getStaticSpecific(a[i]);
            }
        }
        
        a=Packages[name].class.getFields()
        for(let i = 0; i < a.length; i++){
            if(a[i].getName()==String(target)){
                c[a[i].getName()]=this.getStaticSpecific(a[i]);
            }
        }
        
        var bi=[]
        for(let j in c){
            bi.push(c[j])
        }
        
        var res=b
        for(let il in bi){
            res.push(bi[il])
        }
        this.alert(name,res.join("\n\n\n"));
    }
    
    searchMethods(name){
        let view = $ui.inflateXml(this, `
<vertical>
    <android.widget.AutoCompleteTextView id="search" margin="22" />
</vertical>
            `, null);
        var actv = view.findView("search");
        actv.setThreshold(1);
        var bg=new android.graphics.drawable.GradientDrawable();
        bg.setColor(android.graphics.Color.parseColor("#ffffff"));
        bg.setCornerRadius(10);
        //actv.setDropDownBackgroundDrawable(bg);
        var a=Packages[name].class.getMethods();
        var s=[];
        for(let i = 0; i < a.length; i++){
            s.push(a[i].getName()+"");
        }
        a=Packages[name].class.getDeclaredFields();
        var bI={};
        for(let i = 0; i < a.length; i++){
            bI[a[i].getName()]=a[i].getName();
        }
        a=Packages[name].class.getFields();
        for(let i = 0; i < a.length; i++){
            bI[a[i].getName()]=a[i].getName();
        }
        for(let la in bI){
            s.push(bI[la]+"");
        }
        var dial=new MaterialAlertDialogBuilder(this);
        var adapter=new android.widget.ArrayAdapter(this, android.R.layout.simple_list_item_1, s);
        actv.setAdapter(adapter);
        dial.setView(view);
        dial.setTitle("请输入方法或字段名称");
        dial.setPositiveButton("确定", async () => {
            this.showMethod(CurrentName, actv.getText());
        });
        dial.setNegativeButton("取消",{onClick:function(v){}})
        dial.show()
    }
    
    showSpecial(index){
        var spe=this.special[index][1];
        var res=[]
        res.push("介绍:\n      "+this.special[index][2])
        for(var i in spe){
            var buf=i+"("+spe[i][0]+")\n      "+spe[i][1]
            res.push(buf)
        }
      this.alert(this.special[index][0],res.join("\n\n\n"))
    }
    
    onCreate(savedInstanceState){
        
        super.onCreate(savedInstanceState);
    }
    
    async onContentViewSet(contentView) {
        //this.setTheme(com.google.android.material.R$style.Theme_MaterialComponents_DayNight_DarkActionBar);
        this.setSupportActionBar(contentView.findView("toolbar"));
        this.ui.类信息.on("click", async () => {
            let dialog = new MaterialAlertDialogBuilder(this);
            dialog.setTitle("请输入类名");
            let view = $ui.inflateXml(this, `
<column>
    <com.google.android.material.textfield.TextInputLayout margin="22" style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" hint="例如:java.lang.Thread">
        <com.google.android.material.textfield.TextInputEditText id="class_name" imeOptions="actionDone"/>
    </com.google.android.material.textfield.TextInputLayout>
</column>
            `, null);
            dialog.setView(view);
            dialog.setNegativeButton("取消", async () => {
                dialog.dismiss();
            });
            dialog.setPositiveButton("确定", null);
            dialog = dialog.create();
            dialog.show();
            dialog.getButton(android.content.DialogInterface.BUTTON_POSITIVE).setOnClickListener(()=>{
                let net = view.findView("class_name");
                let class_name = net.getText() + "";
                let _Class = $java.findClassOrNull(class_name);
                if (_Class) {
                    this.getInfo(class_name, this.ui.类信息);
                    dialog.dismiss();
                } else {
                    //Snackbar.make(this.contentView, class_name + "是无效类名。", -1).show();
                    //toast(class_name + "是无效类名。");
                    view.findView("class_name").setError(class_name + "是无效类名。");
                    //this.ui.类信息.emit("click");
                }
            })
            
            
        });
    }

    getInfo(name, button) {
        CurrentName = name;
        var d = new MaterialAlertDialogBuilder(this);
        var arr = ["字段", "方法", "构造函数", "搜索方法和字段", "详细信息", "原始方法", "原始字段"]
        
        for (this.index = 0; this.index < this.special.length; this.index++) {
            if (this.special[this.index][0] == name) {
                arr.push("特别介绍");
                break
            }
        }
        var adapter = new android.widget.ArrayAdapter(this, android.R.layout.simple_list_item_1, arr);
        var listl = new android.widget.ListView(this);
        listl.setAdapter(adapter);
        listl.setOnItemClickListener(
            new android.widget.AdapterView.OnItemClickListener({
                onItemClick: (v, unknown, index) => {
                    switch (index) {
                        case 0:
                            this.getStatic(CurrentName)
                            break
                        case 1:
                            this.getMethods(CurrentName)
                            break
                        case 2:
                            this.getConstructors(CurrentName)
                            break
                        case 3:
                            this.searchMethods(CurrentName)
                            break
                        case 4:
                            this.getMainInfo(CurrentName)
                            break
                        case 5:
                            var gi3 = Packages[CurrentName].class.getDeclaredMethodsUnchecked(true);
                            var arria3 = [];
                            for (var suxj = 0; suxj < gi3.length; suxj++) {
                                arria3.push(this.getMethod(gi3[suxj]))
                            }
                            this.alert("原始方法", arria3.join("\n\n\n"));
                            break
                        case 6:
                            var gi3 = Packages[CurrentName].class.getDeclaredFieldsUnchecked(true);
                            var arria3 = [];
                            for (var suxj = 0; suxj < gi3.length; suxj++) {
                                arria3.push(this.getStaticSpecific(gi3[suxj]));
                            }
                            this.alert("原始字段", arria3.join("\n\n\n"));
                            break
                        case 7:
                            toast(""+index)
                            this.showSpecial(this.index);
                            break
                    }
                }
            })
        )
        d.setTitle(name)
        d.setView(listl)
        d.setPositiveButton("确定", () => {
            button.emit("click");
        })
        d.show()
    }
}

$ui.setMainActivity(MyActivity);
$ui.activityLifecycle.on("all_activities_destroyed", () => {
    process.exit();
});

